package com.gryffonx.NameGenerators;

import com.gryffonx.DiceRoller.StaticDiceRoller;
import com.gryffonx.utils.StringUtils;
import com.gryffonx.utils.XMLUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import java.io.File;

/**
 * Currently has 14 different ways to generate a city name.  A random number is generated to determine
 * the rule to be used.  Once the rule has been identified, the name is built using further methods that
 * depend on random numbers.  The rules are simply a series of arrangements of prefix, mid, and suffix elements
 * with different grammatical treatments
 *
 * @author Erik Stell
 * @version 1.0
 */
public class CityNameGenerator {
    private static final File fileToBeParsed = new File("src/com/gryffonx/xml/city.xml");
    private static final SAXReader reader = new SAXReader();
    private static Document xmlDoc = null;

    public static String generateName(int howMany) {
        StringBuffer retVal = new StringBuffer();

        if (howMany <= 0) {
            howMany = 1;
        }

        try {
            xmlDoc = reader.read(fileToBeParsed);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (int i = 0; i < howMany; i++) {
            StringBuffer finishedName = new StringBuffer();
            try {
                int rule = determineRule();
                if (rule == 1) {
                    finishedName.append(generateRule1());
                } else if (rule == 2) {
                    finishedName.append(generateRule2());
                } else if (rule == 3) {
                    finishedName.append(generateRule3());
                } else if (rule == 4) {
                    finishedName.append(generateRule4());
                } else if (rule == 5) {
                    finishedName.append(generateRule5());
                } else if (rule == 6) {
                    finishedName.append(generateRule6());
                } else if (rule == 7) {
                    finishedName.append(generateRule7());
                } else if (rule == 8) {
                    finishedName.append(generateRule8());
                } else if (rule == 9) {
                    finishedName.append(generateRule9());
                } else if (rule == 10) {
                    finishedName.append(generateRule10());
                } else if (rule == 11) {
                    finishedName.append(generateRule11());
                } else if (rule == 12) {
                    finishedName.append(generateRule12());
                } else if (rule == 13) {
                    finishedName.append(generateRule13());
                } else if (rule == 14) {
                    finishedName.append(generateRule14());
                } else if (rule == 15) {
                    finishedName.append(generateRule15());
                } else if (rule == 16) {
                    finishedName.append(generateRule16());
                } else if (rule == 17) {
                    finishedName.append(generateRule17());
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            retVal.append(StringUtils.capitalize(finishedName.toString()));
            // retVal.append("\n");
        }
        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix, 2 middle elements, and a suffix.
     *
     * @return
     */
    private static String generateRule1() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(1));
        retVal.append(getMid(2));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix and a suffix.
     *
     * @return
     */
    private static String generateRule2() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix, middle element, and a suffix.
     *
     * @return
     */
    private static String generateRule3() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(1));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix, middle element from series 2, and a suffix.
     *
     * @return
     */
    private static String generateRule4() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(2));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 2, a space, another prefix from series 1,
     * a middle element from series 2, and a suffix.
     *
     * @return
     */
    private static String generateRule5() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(2));
        retVal.append(" ");
        retVal.append(getPrefix(1));
        retVal.append(getMid(2));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 1, a middle element from series 2, a standard suffix a space,
     * and another prefix from series 2.
     * and a suffix.
     *
     * @return
     */
    private static String generateRule6() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(2));
        retVal.append(getSuffix());
        retVal.append(" ");
        retVal.append(getPrefix(2));


        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 2, a space, another prefix from series 1,
     * a middle element from series 1, and a suffix.
     *
     * @return
     */
    private static String generateRule7() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(2));
        retVal.append(" ");
        retVal.append(getPrefix(1));
        retVal.append(getMid(1));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 2, a space, another prefix from series 1,
     * and a suffix.
     *
     * @return
     */
    private static String generateRule8() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(2));
        retVal.append(" ");
        retVal.append(getPrefix(1));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 1, and middle element from series 1, a standard suffix
     * a space, another prefix from series 2,
     * and a suffix.
     *
     * @return
     */
    private static String generateRule9() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(1));
        retVal.append(getSuffix());
        retVal.append(" ");
        retVal.append(getPrefix(2));


        return retVal.toString();
    }

    private static String generateRule10() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getSuffix());
        retVal.append(" ");
        retVal.append(getPrefix(2));


        return retVal.toString();
    }

    private static String generateRule11() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(2));
        retVal.append(" ");
        retVal.append(getMid(1).toUpperCase());
        retVal.append("' ");
        retVal.append(getPrefix(1));
        retVal.append(getSuffix());


        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 1, middle element from series 3, and a suffix.
     *
     * @return
     */
    private static String generateRule12() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(3));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    /**
     * Generates a city name using a standard prefix from series 2, a space, another prefix from series 1,
     * a middle element from series 3, and a suffix.
     *
     * @return
     */
    private static String generateRule13() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(2));
        retVal.append(" ");
        retVal.append(getPrefix(1));
        retVal.append(getMid(3));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    private static String generateRule14() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(3));
        retVal.append(getSuffix());
        retVal.append(" ");
        retVal.append(getPrefix(2));


        return retVal.toString();
    }


    private static String generateRule15() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(3));
        retVal.append(getSuffix());
        retVal.append(" ");
        retVal.append(getPrefix(3));


        return retVal.toString();
    }

    private static String generateRule16() {
        StringBuffer retVal = new StringBuffer();

        retVal.append("The ");
        retVal.append(getPrefix(3));
        retVal.append(" of ");
        retVal.append(getPrefix(1));
        retVal.append(getMid(3));
        retVal.append(getSuffix());

        return retVal.toString();
    }

    private static String generateRule17() {
        StringBuffer retVal = new StringBuffer();

        retVal.append(getPrefix(1));
        retVal.append(getMid(3));
        retVal.append(getSuffix());
        retVal.append("'s ");
        retVal.append(getPrefix(3));


        return retVal.toString();
    }

    private static int determineRule() {
        return StaticDiceRoller.rolldSomething(17, 1);
    }

    private static String getPrefix(int group) {
        String retVal = "";
        try {
            retVal = StringUtils.capitalize(XMLUtils.getNodeValue("prefix", xmlDoc, group));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retVal;
    }

    private static String getMid(int group) {
        String retVal = "";
        try {
            retVal = XMLUtils.getNodeValue("middle", xmlDoc, group);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retVal;
    }

    private static String getSuffix() {
        String retVal = "";
        try {
            retVal = XMLUtils.getNodeValue(xmlDoc, "nation");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retVal;
    }
}